package libs.yzx.zaza.za;

import android.animation.ValueAnimator;
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.AbsListView;
import android.widget.LinearLayout;

public abstract class AbsPullLayout extends LinearLayout {

    public AbsPullLayout(Context context) {
        this(context, null);
    }

    public AbsPullLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOrientation(VERTICAL);

        headerView = getHeader();
        headerHeight = getHeaderHeight();
        boundaryLength = getBoundaryLength();
        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(-1, headerHeight);
        lp.topMargin = -headerHeight;
        headerView.setLayoutParams(lp);
        addView(headerView, 0);
    }


    //==//


    private final View headerView;
    private final int boundaryLength;
    private final int headerHeight;
    private final int touchSlop;

    private float interceptDownY;
    private float lastTouchY;

    private static final int state_normal = 1;
    private static final int state_ready = 2;
    private static final int state_loading = 3;
    private int state = -1;

    private final static int anim_time = 150;
    private ValueAnimator anim;


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (letChildTouch())
            return false;
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            lastTouchY = interceptDownY = ev.getRawY();
            return false;
        } else {
            if (!canChildScrollUp())
                if (ev.getRawY() - interceptDownY > touchSlop)
                    return true;
        }
        lastTouchY = ev.getRawY();
        return false;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (letChildTouch())
            return false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                lastTouchY = event.getRawY();
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                float nowTouchY = event.getRawY();
                float gap = nowTouchY - lastTouchY;
                lastTouchY = nowTouchY;
                int nowMargin = getHeaderMargin();

                if (nowMargin <= getHeaderNoneMargin() && gap < 0) {
                    setHeaderMargin(getHeaderNoneMargin());
                    return true;
                }

                setHeaderMarginRelative((int) (gap / 2));

                if (getHeaderMargin() >= getHeaderLoadingMargin()) {
                    if (state != state_ready) {
                        setPullReadyUI(headerView);
                        state = state_ready;
                    }
                } else {
                    if (state != state_normal) {
                        setPullNormalUI(headerView);
                        state = state_normal;
                    }
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
                if (state == state_ready) {
                    setPullLoadingUI(headerView);
                    if (onRefreshListener != null)
                        onRefreshListener.onRefresh(this);
                    animHeaderToLoading();
                    state = state_loading;
                } else {
                    setPullNormalUI(headerView);
                    animHeaderToNone();
                    state = state_normal;
                }
                break;
            }
        }
        return true;
    }


    /*
     *@@摘自 SwipeRefreshLayout
     *让子view接收事件的时候, 每次都会执行父类的onInterceptTouchEvent方法
     * (ListView等滑动的时候,会执行requestDisallowInterceptTouchEvent方法,父View会跳过onInterceptTouchEvent方法)
     */
    @Override
    public void requestDisallowInterceptTouchEvent(boolean b) {
        View mTarget = getChildAt(1);
        if ((android.os.Build.VERSION.SDK_INT < 21 && mTarget instanceof AbsListView) || (mTarget != null && !ViewCompat.isNestedScrollingEnabled(mTarget))) {
            //empty
        } else
            super.requestDisallowInterceptTouchEvent(b);
    }


    /*
     * 设置header的相对topMargin
     */
    private void setHeaderMarginRelative(int rel) {
        if (rel == 0)
            return;
        LinearLayout.LayoutParams lp = (LayoutParams) headerView.getLayoutParams();
        lp.topMargin += rel;
        headerView.requestLayout();
    }


    /*
     * 设置header的绝对topMargin
     */
    private void setHeaderMargin(int m) {
        LinearLayout.LayoutParams lp = (LayoutParams) headerView.getLayoutParams();
        if (lp.topMargin == m)
            return;
        lp.topMargin = m;
        headerView.requestLayout();
    }


    /*
     * 当前header的topMargin
     */
    private int getHeaderMargin() {
        LinearLayout.LayoutParams lp = (LayoutParams) headerView.getLayoutParams();
        return lp.topMargin;
    }


    /*
     * view是否能往上划拉滚动
     */
    private boolean canChildScrollUp() {
        View mTarget = getChildAt(1);
        if (android.os.Build.VERSION.SDK_INT < 14) {
            if (mTarget instanceof AbsListView) {
                final AbsListView absListView = (AbsListView) mTarget;
                return absListView.getChildCount() > 0 && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0).getTop() < absListView.getPaddingTop());
            } else
                return ViewCompat.canScrollVertically(mTarget, -1) || mTarget.getScrollY() > 0;
        } else
            return ViewCompat.canScrollVertically(mTarget, -1);
    }


    /*
     * 不拦截touch事件的情况
     */
    private boolean letChildTouch() {
        return state == state_loading || anim != null || !enable;
    }


    /*
     * loading 状态下,header的margin
     */
    private int getHeaderLoadingMargin() {
        return boundaryLength - headerHeight;
    }


    /*
     * none状态下 , header的margin
     */
    private int getHeaderNoneMargin() {
        return -headerHeight;
    }


    /*
     * 执行动画,将header一到初始位置
     */
    private void animHeaderToNone() {
        if (anim != null)
            anim.cancel();
        if (getHeaderMargin() == getHeaderNoneMargin())
            return;
        anim = ValueAnimator.ofInt(getHeaderMargin(), getHeaderNoneMargin()).setDuration(getAnimDuration());
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                int now = (int) valueAnimator.getAnimatedValue();
                setHeaderMargin(now);
                if (now == getHeaderNoneMargin())
                    anim = null;
            }
        });
        anim.start();
    }


    /*
    * 执行动画,将header一到loading状态位置
    */
    private void animHeaderToLoading() {
        if (anim != null)
            anim.cancel();
        if (getHeaderMargin() == getHeaderLoadingMargin())
            return;
        anim = ValueAnimator.ofInt(getHeaderMargin(), getHeaderLoadingMargin()).setDuration(getAnimDuration());
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                int now = (int) valueAnimator.getAnimatedValue();
                setHeaderMargin(now);
                if (now == getHeaderLoadingMargin())
                    anim = null;
            }
        });
        anim.start();
    }


    //


    /**
     * 设置刷新状态UI
     */
    public void setRefreshing(final boolean r, final boolean anim) {
        if (AbsPullLayout.this.anim != null) {
            AbsPullLayout.this.anim.cancel();
            AbsPullLayout.this.anim = null;
        }
        post(new Runnable() {
            public void run() {
                if (r) {
                    setPullLoadingUI(headerView);
                    if (anim)
                        animHeaderToLoading();
                    else
                        setHeaderMargin(getHeaderLoadingMargin());
                    state = state_loading;
                } else {
                    if (anim)
                        animHeaderToNone();
                    else
                        setHeaderMargin(getHeaderNoneMargin());
                    setPullNormalUI(headerView);
                    state = state_normal;
                }
            }
        });
    }


    //


    protected abstract View getHeader();

    //刷新状态中, header出现的高度距离
    protected abstract int getBoundaryLength();

    protected abstract int getHeaderHeight();

    protected abstract void setPullNormalUI(View header);

    protected abstract void setPullReadyUI(View header);

    protected abstract void setPullLoadingUI(View header);

    protected int getAnimDuration() {
        return anim_time;
    }


    //

    private OnRefreshingListener onRefreshListener;

    /**
     * 设置刷新回调监听
     */
    public void setOnRefreshListener(OnRefreshingListener onRefreshListener) {
        this.onRefreshListener = onRefreshListener;
    }

    public interface OnRefreshingListener {
        void onRefresh(AbsPullLayout layout);
    }

    private boolean enable = true;

    /**
     * 设置可用
     */
    public void setEnable(boolean enable) {
        boolean change = (this.enable != enable);
        if (!change)
            return;
        this.enable = enable;
        state = state_normal;
        setHeaderMargin(getHeaderNoneMargin());
        setPullNormalUI(headerView);
    }

}